// 保留谷老师js版实现

import GrimmPopup from '../Popup/index.vue'
import BScroll from 'better-scroll'
import visibilityMixin from '../../common/mixins/visibility'
import popupMixin from '../../common/mixins/popup'
import basicPickerMixin from '../../common/mixins/basic-picker'
import pickerMixin from '../../common/mixins/picker'
const name = 'grimm-picker'
const EVENT_SELECT = 'select'
const EVENT_VALUE_CHANGE = 'value-change'
const EVENT_CANCEL = 'cancel'
const EVENT_CHANGE = 'change'

export default {
  name,
  components: { GrimmPopup },
  mixins: [visibilityMixin, popupMixin, basicPickerMixin, pickerMixin],
  props: {
    pending: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      finalData: this.data.slice()
    }
  },
  created() {
    this._values = []
    this._indexes = this.selectedIndex
  },
  methods: {
    confirm() {
      if (!this._canConfirm()) {
        return
      }
      this.hide()

      let changed = false
      let pickerSelectedText = []

      const { length } = this.finalData
      const oldLength = this._values.length

      // when column count has changed.
      if (oldLength !== length) {
        changed = true
        oldLength > length && (this._values.length = this._indexes.length = length)
      }

      for (let i = 0; i < length; i++) {
        let index = this.wheels[i].getSelectedIndex()
        this._indexes[i] = index

        let value = null
        let text = ''
        if (this.finalData[i].length) {
          value = this.finalData[i][index][this.valueKey]
          text = this.finalData[i][index][this.textKey]
        }
        if (this._values[i] !== value) {
          changed = true
        }
        this._values[i] = value
        pickerSelectedText[i] = { value, text }
      }

      this.$emit(EVENT_SELECT, this._values, this._indexes, pickerSelectedText)

      if (changed) {
        this.$emit(EVENT_VALUE_CHANGE, this._values, this._indexes, pickerSelectedText)
      }
    },
    maskClick() {
      this.maskClosable && this.cancel()
    },
    cancel() {
      this.hide()
      this.$emit(EVENT_CANCEL)
    },
    show() {
      if (this.isVisible) {
        return
      }

      this.isVisible = true
      if (!this.wheels || this.dirty) {
        this.$nextTick(() => {
          this.wheels = this.wheels || []
          let { wheelWrapper } = this.$refs
          for (let i = 0; i < this.finalData.length; i++) {
            this._createWheel(wheelWrapper, i).enable()
            this.wheels[i].wheelTo(this._indexes[i])
          }
          this.dirty && this._destroyExtraWheels()
          this.dirty = false
        })
      } else {
        for (let i = 0; i < this.finalData.length; i++) {
          this.wheels[i].enable()
          this.wheels[i].wheelTo(this._indexes[i])
        }
      }
    },
    hide() {
      if (!this.isVisible) {
        return
      }
      this.isVisible = false

      for (let i = 0; i < this.finalData.length; i++) {
        this.wheels[i].disable()
      }
    },
    setData(data, selectedIndex) {
      this._indexes = selectedIndex ? [...selectedIndex] : []
      this.finalData = data.slice()
      if (this.isVisible) {
        this.$nextTick(() => {
          const { wheelWrapper } = this.$refs
          this.finalData.forEach((item, i) => {
            this._createWheel(wheelWrapper, i)
            this.wheels[i].wheelTo(this._indexes[i])
          })
          this._destroyExtraWheels()
        })
      } else {
        this.dirty = true
      }
    },
    refill(datas) {
      let ret = []
      if (!datas.length) {
        return ret
      }
      datas.forEach((data, index) => {
        ret[index] = this.refillColumn(index, data)
      })
      return ret
    },
    refillColumn(index, data) {
      const { wheelWrapper } = this.$refs
      let scroll = wheelWrapper.children[index].querySelector('.grimm-picker-wheel-scroll')
      let wheel = this.wheels ? this.wheels[index] : false
      let dist = 0
      if (scroll && wheel) {
        let oldData = this.finalData[index]
        this.$set(this.finalData, index, data)
        let selectedIndex = wheel.getSelectedIndex()
        if (oldData.length) {
          let oldValue = oldData[selectedIndex][this.valueKey]
          for (let i = 0; i < data.length; i++) {
            if (data[i][this.valueKey] === oldValue) {
              dist = i
              break
            }
          }
        }
        this._indexes[index] = dist
        this.$nextTick(() => {
          wheel = this._createWheel(wheelWrapper, index)
          wheel.wheelTo(dist)
        })
      }
      return dist
    },
    scrollTo(index, dist) {
      const wheel = this.wheels[index]
      this._indexes[index] = dist
      wheel.wheelTo(dist)
    },
    refresh() {
      this.$nextTick(() => {
        this.wheels.forEach((wheel) => {
          wheel.refresh()
        })
      })
    },
    _createWheel(wheelWrapper, i) {
      if (!this.wheels[i]) {
        const wheel = this.wheels[i] = new BScroll(wheelWrapper.children[i], {
          wheel: {
            selectedIndex: this._indexes[i] || 0,
            wheelWrapperClass: 'grimm-picker-wheel-scroll',
            wheelItemClass: 'grimm-picker-wheel-item'
          },
          swipeTime: this.swipeTime,
          observeDOM: false
        })
        wheel.on('scrollEnd', () => {
          this.$emit(EVENT_CHANGE, i, wheel.getSelectedIndex())
        })
      } else {
        this.wheels[i].refresh()
      }
      return this.wheels[i]
    },
    _destroyExtraWheels() {
      const dataLength = this.finalData.length
      if (this.wheels.length > dataLength) {
        const extraWheels = this.wheels.splice(dataLength)
        extraWheels.forEach((wheel) => {
          wheel.destroy()
        })
      }
    },
    _canConfirm() {
      return !this.pending && this.wheels.every((wheel) => {
        return !wheel.isInTransition
      })
    },
    _getFlexOrder(data) {
      if (data[0]) {
        return data[0][this.orderKey]
      }
      return 0
    },
    header() {
      const h = this.$createElement
      const children = [h('h1', { 'class': `${name}-title` }, this.title)]
      if (this.subtitle) {
        children.push(h('h1', { 'class': `${name}-subtitle` }, this.subtitle))
      }
      return h('div', { 'class': `${name}-choose border-bottom-1px` }, [
        h('span', { 'class': `${name}-cancel`, on: { click: this.cancel } }, this._cancelTxt),
        h('span', { 'class': `${name}-confirm`, on: { click: this.confirm } }, this._confirmTxt),
        h('div', { 'class': `${name}-title-group` }, children)
      ])
    },
    body() {
      const h = this.$createElement
      const children = this.finalData.map(item => {
        const subChildren = item.map(subItem => {
          return h('li', { 'class': `${name}-wheel-item` }, [subItem[this.textKey]])
        })
        const subChild = h('ul', { 'class': `${name}-wheel-scroll` }, subChildren)
        // TODO :style binding
        return h('div', { style: { order: this._getFlexOrder(item) } }, [subChild])
      })
      return h('div', { 'class': `${name}-content` }, [
        h('i', { 'class': 'border-bottom-1px' }),
        h('i', { 'class': 'border-top-1px' }),
        h('div', { 'class': `${name}-wheel-wrapper`, ref: 'wheelWrapper' }, children)
      ])
    }
  },
  beforeDestroy() {
    this.wheels && this.wheels.forEach((wheel) => {
      wheel.destroy()
    })
    this.wheels = null
  },
  render(h) {
    return h(
      'transition',
      { domProps: { name: `${name}-fade` } },
      [
        h(
          'GrimmPopup',
          {
            'class': name,
            props: {
              visible: this.isVisible,
              position: 'bottom',
              type: 'picker',
              mask: true,
              center: false,
              zIndex: 100,
            },
            on: {
              'mask-click': this.maskClick,
              touchmove(evt) { evt.preventDefault() }
            }
          },
          [
            h('transition', { domProps: { name: `${name}-move` } },
              [
                h('div', { 'class': `${name}-panel grimm-safe-area-pb` }, [this.header(), this.body()])
              ]
            )
          ]
        )
      ]
    )
  }
}
